package cn.xuqiudong.common.blog.search.lookup;

import cn.xuqiudong.common.base.lookup.Lookup;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.util.Assert;

import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * 描述:
 *
 * @author Vic.xu
 * @since 2024-06-07 14:38
 */
public class SearchLookup<T> extends Lookup {
    private static final long serialVersionUID = 1L;

    /**
     * 索引
     */
    public String indexName;
    /**
     * 关键字
     */
    private String keyword;

    /**
     * 滚动分页的id ;暂时未使用
     */
    private String scrollId;

    /**
     * 查询结果对象
     */
    private Class<T> clazz;

    /**
     * key为需要高亮字段，value为对应的set函数<br/>
     * eg： key:    title
     *     value :  (model, text)->{mode.setTitle(text)}
     */
    private Map<String, BiConsumer<T, String>> highlightFieldAndSetFunctionMap = new HashMap<String, BiConsumer<T, String>>();

    /**
     * 构建lookup的入口
     * @param <T> 泛型
     * @param indexName 索引名
     * @param clazz 返回的model类型
     * @return
     */
    public static <T> SearchLookup<T> build(String indexName, Class<T> clazz) {
        SearchLookup<T> lookup = new SearchLookup<T>();
        lookup.setIndexName(indexName);
        lookup.setClazz(clazz);
        return lookup;
    }

    /**
     * 构建关键词
     * @param keyword 搜索的关键词
     */
    public SearchLookup<T> keyword(String keyword) {
        this.keyword = keyword;
        return this;
    }

    /**
     * 构建分页
     * @param page 页码
     * @param size 每页数量
     */
    public SearchLookup<T> page(int page, int size) {
        this.setPage(page);
        this.setSize(size);
        return this;
    }

    /**
     * 构建高亮字段，以及高亮字段的set方法
     * @param field 高亮字段名
     * @param bc 字段名的set方法
     */
    public SearchLookup<T> addHighlightFieldAndSetFunctionString(String field, BiConsumer<T, String> bc) {
        highlightFieldAndSetFunctionMap.put(field, bc);
        return this;
    }

    /**
     * 构建高亮字段，以及高亮字段的set方法
     * @param map  高亮字段名->字段名的set方法
     */
    public SearchLookup<T> addHighlightFieldAndSetFunctionString(Map<String, BiConsumer<T, String>> map) {
        highlightFieldAndSetFunctionMap.putAll(map);
        return this;
    }

    /**
     * 结束构建lookup并检测合法性
     */
    public SearchLookup<T> end() {
        Assert.hasText(keyword, "keyword不可为空");
        Assert.hasText(indexName, "indexName不可为空");
        Assert.isTrue(highlightFieldAndSetFunctionMap.size() > 0, "必须包含高亮字段，以及对应的set方法");
        return this;
    }


    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getScrollId() {
        return scrollId;
    }

    public void setScrollId(String scrollId) {
        this.scrollId = scrollId;
    }

    @SuppressWarnings("unchecked")
    public Class<T> getClazz() {
        if (clazz == null) {
            clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return clazz;
    }

    public void setClazz(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Map<String, BiConsumer<T, String>> getHighlightFieldAndSetFunctionMap() {
        return highlightFieldAndSetFunctionMap;
    }

    public void setHighlightFieldAndSetFunctionMap(Map<String, BiConsumer<T, String>> highlightFieldAndSetFunctionMap) {
        this.highlightFieldAndSetFunctionMap = highlightFieldAndSetFunctionMap;
    }

    public String getIndexName() {
        return indexName;
    }

    public void setIndexName(String indexName) {
        this.indexName = indexName;
    }


}

